#include <iostream>
#include <assert.h>
using namespace std;
template<class SLTDateType>
struct Node
{
    SLTDateType data;
    Node<SLTDateType>* next;
    Node(const SLTDateType& val)//节点初始化构造函数
    :data(val)
    ,next(nullptr)
    {}
};

template<class SLTDateType>
class SListNode
{
public:
    SListNode()//初始化开空间构造函数
    {

        head=new Node<SLTDateType>(SLTDateType());
    }

    ~SListNode()
{
    Node<SLTDateType>* cur = head->next;
    while (cur)
    {
        Node<SLTDateType>* next = cur->next;//记录下个节点位置
        delete cur;//释放当前节点
        cur = next;//移动光标到下个节点
    }
    head->next = nullptr;//最后一个节点置空
    delete head;
    head= nullptr;
    cout << "Destory" << endl;
}

// 单链表打印
    void SListPrint();
// 单链表尾插
    void SListPushBack(SLTDateType val);
// 单链表的头插
    void SListPushFront(SLTDateType val);
// 单链表的尾删
    void SListPopBack();
// 单链表头删
    void SListPopFront();
// 单链表查找
    Node<SLTDateType>* SListFind(SLTDateType val);
// 单链表在pos位置之后插入x
// 分析思考为什么不在pos位置之前插入？
    void SListInsertAfter(Node<SLTDateType>* pos, SLTDateType val);
// 单链表删除pos位置之后的值
// 分析思考为什么不删除pos位置？
    void SListEraseAfter(Node<SLTDateType>* pos);
//// 单链表的销毁
//    void SListDestroy(SListNode* plist);
////删除pos位置节点
    void SListErase(Node<SLTDateType>* pos);

private:
    Node<SLTDateType>* head;
};



// 单链表打印
template<class SLTDateType>
void SListNode<SLTDateType>::SListPrint()
{
    assert(head);
    Node<SLTDateType>* cur = head->next;
    while (cur)
    {
        cout << cur->data << " --> ";
        cur = cur->next;
    }
    cout << "nullptr" << endl;
}

// 单链表尾插
template<class SLTDateType>
void SListNode<SLTDateType>::SListPushBack(SLTDateType val)
{
    assert(head);
    Node<SLTDateType>* newNode =new Node<SLTDateType>(val);
    Node<SLTDateType>* tail = head;
    while (tail->next)
    {
        tail = tail->next;
    }
    tail->next = newNode;


}
// 单链表的头插
template<class SLTDateType>
void SListNode<SLTDateType>::SListPushFront(SLTDateType val)
{
    assert(head);
    Node<SLTDateType>* newNode =new Node<SLTDateType>(val);
    newNode->next=head->next;
    head->next=newNode;

}
// 单链表的尾删
template<class SLTDateType>
void SListNode<SLTDateType>:: SListPopBack()
{
    assert(head->next);
    Node<SLTDateType>* cur = head;
    while (cur->next->next)
    {
        cur = cur->next;
    }
    delete cur->next;
    cur->next = nullptr;

}
// 单链表头删
template<class SLTDateType>
void SListNode<SLTDateType>::SListPopFront()
{
    assert(head->next);
    Node<SLTDateType>* cur = head->next;
    head->next = head->next->next;
    delete cur;
    cur= nullptr;

}
// 单链表查找
template<class SLTDateType>
Node<SLTDateType>* SListNode<SLTDateType>::SListFind(SLTDateType val)
{
    assert(head->next);
    Node<SLTDateType>* cur = head->next;
    while (cur)
    {
        if(cur->data==val)
        {
            return cur;
        }
        else
        {
            cur = cur->next;
        }

    }
    return nullptr;//找不到时返回空值
}

// 单链表在pos位置之后插入x
// 分析思考为什么不在pos位置之前插入？//单链表找不到prev节点
template<class SLTDateType>
void  SListNode<SLTDateType>:: SListInsertAfter(Node<SLTDateType>* pos, SLTDateType val)
{
    assert(pos);
    Node<SLTDateType>* newNode = new Node<SLTDateType>(val);
    newNode->next = pos->next; //让新节点指向pos后的节点
    pos->next= newNode;//pos位置之后的节点变成新节点
}
// 单链表删除pos位置之后的值
// 分析思考为什么不删除pos位置？//单链表删除pos后pos的prev节点无法链接pos->next
template<class SLTDateType>
void SListNode<SLTDateType>::SListEraseAfter(Node<SLTDateType>* pos)
{
    assert(pos);
    if (pos->next == NULL) return;
    else
    {
        Node<SLTDateType>* nextNode = pos->next;
        pos->next = nextNode->next;//pos->next->next;
        delete nextNode;
        nextNode= nullptr;
    }
}

//删除pos位置节点
template<class SLTDateType>
void SListNode<SLTDateType>::SListErase(Node<SLTDateType>* pos)
{
    assert(pos);
    assert(head->next);
    if (head->next == pos)//就一个节点时
    {
        (*this).SListPopFront();//头删
    }
    else
    {
        Node<SLTDateType>* cur = head->next;
        while(cur->next != pos)//找到pos时 cur=pos的前一个节点
        {
            cur = cur->next;
        }
        cur->next = pos->next;//cur的下一个节点是要删除的pos pos 的下一个节点是要连接的节点
        delete pos;//删除pos
        pos= nullptr;
    }
}